package com.example.contentproviders;

import java.util.HashMap;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.util.Log;

public class CitizenContentProvider extends ContentProvider {

	public static final String AUTHORITY = "jwei.apps.dataforandroid.ch4.CitizenContentProvider";

	private static final UriMatcher mUriMathcer;
	private static HashMap<String, String> projectionMap;

	// URI MATCH OF A GENERAL CITIZENS QUERY
	private static final int CITIZENS = 1;
	// URI MATCH OF A SPECIFIC CITIZEN QUERY
	private static final int SSID = 2;
	// INSTANTIATE AND SET STATIC VARIABLES
	static {
		mUriMathcer = new UriMatcher(UriMatcher.NO_MATCH);
		mUriMathcer.addURI(AUTHORITY, "citizen", CITIZENS);
		mUriMathcer.addURI(AUTHORITY, "citizen/#", SSID);
		// projection map used for row alias
		projectionMap = new HashMap<String, String>();
		projectionMap.put(CitizenTable.ID, CitizenTable.ID);
		projectionMap.put(CitizenTable.NAME, CitizenTable.NAME);
		projectionMap.put(CitizenTable.STATE, CitizenTable.STATE);
		projectionMap.put(CitizenTable.INCOME, CitizenTable.INCOME);
	}

	private static class SqliteHelper extends SQLiteOpenHelper {

		private static final String DATABASE_NAME = "citizen.db";
		private static final int DATABASE_VERSION = 1;

		public SqliteHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}

		@Override
		public void onCreate(SQLiteDatabase db) {
			String sql = ("CREATE TABLE " + CitizenTable.TABLE_NAME + " ( "
					+ CitizenTable.ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
					+ CitizenTable.NAME + " TEXT, " + CitizenTable.STATE
					+ " TEXT, " + CitizenTable.INCOME + " INTEGER);");
			db.execSQL(sql);
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			String sql = "DROP TABLE IF EXISTS " + CitizenTable.TABLE_NAME;
			db.execSQL(sql);
			onCreate(db);
		}
	}

	private SqliteHelper sqh;

	@Override
	public boolean onCreate() {
		sqh = new SqliteHelper(getContext());
		return true;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
		qb.setTables(CitizenTable.TABLE_NAME);

		switch (mUriMathcer.match(uri)) {
		case CITIZENS:
			qb.setProjectionMap(projectionMap);
			break;
		case SSID:
			String ssid = uri.getPathSegments().get(
					CitizenTable.SSID_PATH_POSITION);
			qb.setProjectionMap(projectionMap);
			qb.appendWhere(CitizenTable.ID + "=" + ssid);
			break;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
		SQLiteDatabase sqdb = sqh.getReadableDatabase();
		Cursor c = qb.query(sqdb, projection, selection, selectionArgs, null,
				null, sortOrder);
		// REGISTERS NOTIFICATION LISTENER WITH GIVEN CURSOR
		// CURSOR KNOWS WHEN UNDERLYING DATA HAS CHANGED
		c.setNotificationUri(getContext().getContentResolver(), uri);

		return c;
	}

	@Override
	public String getType(Uri uri) {
		switch (mUriMathcer.match(uri)) {
		case CITIZENS:
			return CitizenTable.CONTENT_TYPE;
		case SSID:
			return CitizenTable.CONTENT_ITEM_TYPE;

		default:
			throw new IllegalArgumentException("Unknown URI" + uri);
		}

	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		// only general citizens uri is allowed for insert
		// doesn't make sense to specify a single citizen
		if (mUriMathcer.match(uri) != CITIZENS) {
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
		// package desired values as a contentvlues object
		ContentValues cv;
		if (values != null) {
			cv = new ContentValues(values);
		} else {
			cv = new ContentValues();
		}

		SQLiteDatabase sqdb = sqh.getWritableDatabase();
		long rowId = sqdb.insert(CitizenTable.TABLE_NAME, CitizenTable.NAME,
				values);
		if (rowId > 0) {
			Uri citizenUri = ContentUris.withAppendedId(
					CitizenTable.CONTENT_URI, rowId);
			// notify context of the change
			getContext().getContentResolver().notifyChange(uri, null);
			return citizenUri;
		} else {
			Log.e("failed to insert row into ", uri.toString());
			return null;
		}

	}

	@Override
	public int delete(Uri uri, String where, String[] whereArgs) {
		SQLiteDatabase sqdb = sqh.getWritableDatabase();
		int count;
		switch (mUriMathcer.match(uri)) {
		case CITIZENS:
			// perform regular delete
			count = sqdb.delete(CitizenTable.TABLE_NAME, where, whereArgs);
			break;
		case SSID:
			// from incoming uri get ssid
			String ssid = uri.getPathSegments().get(
					CitizenTable.SSID_PATH_POSITION);
			// user wants to delete a specific citizen
			String finalWhere = CitizenTable.ID + "=" + ssid;
			// if user specifies where filter then append
			if (where != null) {
				finalWhere = finalWhere + " AND " + where;
			}
			count = sqdb.delete(CitizenTable.TABLE_NAME, finalWhere, whereArgs);
			break;

		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		getContext().getContentResolver().notifyChange(uri, null);

		return count;
	}

	@Override
	public int update(Uri uri, ContentValues values, String where,
			String[] whereArgs) {
		SQLiteDatabase sqdb = sqh.getWritableDatabase();
		int count;
		switch (mUriMathcer.match(uri)) {
		case CITIZENS:
			// general update on all citizens
			count = sqdb.update(CitizenTable.TABLE_NAME, values, where,
					whereArgs);
			break;
		case SSID:
			// from incoming uri get ssid
			String ssid = uri.getPathSegments().get(
					CitizenTable.SSID_PATH_POSITION);
			// the user wants to update a specific citizen
			String finalWhere = CitizenTable.ID + "=" + ssid;
			if (where != null) {
				finalWhere = finalWhere + " AND " + where;
			}
			// perform the update on the specific citizen
			count = sqdb.update(CitizenTable.TABLE_NAME, values, finalWhere,
					whereArgs);

			break;
		default:
			throw new IllegalArgumentException("Unknown URI" + uri);
		}
		getContext().getContentResolver().notifyChange(uri, null);

		return count;
	}

}
